package com.seeyon.bugfixtools.custom.datasource.manager;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.seeyon.bugfixtools.custom.datasource.dto.DatasourceDto;
import com.seeyon.bugfixtools.custom.datasource.dto.SystemVersionDto;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;


/**
 * @author cans
 * @date 2024/5/3
 **/
@Component
public class DynamicDataSourceConfig {

    private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceConfig.class);

    @Resource
    private ApplicationContext applicationContext;

    private HikariDataSource hikariDataSource = null;

    public DataSource buildHikariDataSource() {
        this.registerDatasource();
        return hikariDataSource;
    }

    private HikariDataSource createDataSource(DatasourceDto datasourceDto) {
        HikariDataSource newDataSource = DataSourceBuilder.create()
                .url(datasourceDto.getUrl())
                .username(datasourceDto.getUsername())
                .password(datasourceDto.getPassword())
                .type(HikariDataSource.class)
                .build();

        newDataSource.setConnectionTimeout(5000);
        newDataSource.setIdleTimeout(600000);
        return newDataSource;
    }

    public DataSource buildDataSource(DatasourceDto datasourceDto) throws SQLException {
        HikariDataSource dataSource;
        Connection connection = null;
        try {
            dataSource = createDataSource(datasourceDto);
            connection = dataSource.getConnection();
        } catch (Exception e) {
            logger.error("获取数据库连接失败", e);
            throw e;
        } finally {
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    logger.error("关闭数据库连接失败", e);
                }
            }
        }
        this.hikariDataSource = dataSource;

        return hikariDataSource;
    }


    public boolean hasDatasource() {
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        return beanFactory.containsBean("jdbcTemplate");
    }

    public void registerDatasource() {
        if (hikariDataSource != null) {
            JdbcTemplate jdbcTemplate = new JdbcTemplate();
            jdbcTemplate.setDataSource(hikariDataSource);
            DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
            beanFactory.destroySingleton("jdbcTemplate");
            beanFactory.registerSingleton("jdbcTemplate", jdbcTemplate);
        }
    }

    public SystemVersionDto getSystemVersionInfo() {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(this.hikariDataSource);
        return jdbcTemplate.queryForObject("SELECT CONFIG_VALUE,EXT_CONFIG_VALUE FROM ctp_config WHERE CONFIG_CATEGORY='ctp_product_information' AND CONFIG_ITEM='version'", (rs, num) -> {
            SystemVersionDto systemVersionDto = new SystemVersionDto();
            systemVersionDto.setVersion(rs.getString("CONFIG_VALUE"));
            String extConfigValue = rs.getString("EXT_CONFIG_VALUE");
            if (extConfigValue == null) {
                extConfigValue = "[]";
            }
            JsonArray jsonArray = JsonParser.parseString(extConfigValue).getAsJsonArray();
            if (jsonArray != null && jsonArray.size() > 0) {
                JsonObject jsonObject = jsonArray.get(0).getAsJsonObject();
                systemVersionDto.setDeployDateStr(jsonObject.get("updateTime").getAsString());
                systemVersionDto.setBuildId(jsonObject.get("updateVer").getAsString());
            }
            return systemVersionDto;
        });
    }
}
